package com.fz.us.oa.web.shiro.filter;

import com.fz.us.admin.base.bean.Result;
import com.fz.us.admin.base.service.common.ResultService;
import com.fz.us.admin.base.utils.LogUtil;
import com.fz.us.admin.base.utils.mapper.JsonMapper;
import com.fz.us.oa.web.shiro.realm.StatelessWhiteListToken;
import com.fz.us.oa.web.shiro.utils.ShiroRequestUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 白名单的Filter
 */
public class StatelessWhiteListAuthcFilter extends AccessControlFilter {

    @Autowired
    private ResultService resultService;

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

        // 生成 Token
        StatelessWhiteListToken token = new StatelessWhiteListToken();
        token.setAppSign(ShiroRequestUtil.getRequestHeaderWhiteListSign((HttpServletRequest) request));
        token.setParams(ShiroRequestUtil.getRequestHeaderWhiteListMap((HttpServletRequest) request));

        try {
            // 委托给Realm进行登录
            Subject subject = getSubject(request, response);
            subject.login(token);
        } catch (Exception e) {
            String error = null;
            if (e instanceof LockedAccountException){// 锁定的账号
                error = "账号状态异常";
            } else if (e instanceof DisabledAccountException) {// 禁用的账号
                error = "账号状态异常";
            } else if (e instanceof UnknownAccountException){// 错误的账号
                error = "用户名/密码错误";
            } else if (e instanceof ExcessiveAttemptsException){// 登录失败次数过多
                error = "密码输入错误超过5次，请10分钟后再试";
            } else if (e instanceof IncorrectCredentialsException){// 错误的凭证
                error = "用户名/密码错误";
            } else if (e instanceof ExpiredCredentialsException){// 过期的凭证
                error = "用户名/密码错误";
            } else if (e instanceof AuthenticationException){
                error = "您的账号没有访问权限";
            } else {
                error = "账号状态异常";
            }
            String exceptionClassName = (String)request.getAttribute("shiroLoginFailure");
            LogUtil.debug("StatelessAuthcFilter : " + exceptionClassName);
            onLoginFail(response,error); // 登录失败
            return false;
        }
        return true;
    }

    //登录失败时默认返回401状态码
    private void onLoginFail(ServletResponse response,String error) throws IOException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
        String type = "application/json";
        Result result = resultService.error(HttpStatus.FORBIDDEN, error);
        try {
            httpResponse.setContentType(type + ";charset=UTF-8");
            httpResponse.setHeader("Pragma", "No-cache");
            httpResponse.setHeader("Cache-Control", "no-cache");
            httpResponse.setDateHeader("Expires", 0);
            httpResponse.getWriter().write(JsonMapper.nonEmptyMapper().toJson(result));
            httpResponse.getWriter().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
